package loaders

import (
	"context"
	"fmt"
	"path/filepath"
	"time"

	"github.com/unidoc/unipdf/v3/extractor"
	"github.com/unidoc/unipdf/v3/model"
)

// PDFLoader PDF文件加载器
type PDFLoader struct {
	*BaseLoader
	ExtractText   bool
	ExtractImages bool
}

// NewPDFLoader 创建PDF文件加载器
func NewPDFLoader(filePath string) *PDFLoader {
	return &PDFLoader{
		BaseLoader:    NewBaseLoader(filePath),
		ExtractText:   true,
		ExtractImages: false,
	}
}

// Load 加载PDF文件
func (l *PDFLoader) Load(ctx context.Context) ([]Document, error) {
	startTime := time.Now()
	l.logInfo("开始加载PDF文件")

	// 加载PDF文件
	pdfReader, f, err := model.NewPdfReaderFromFile(l.FilePath, nil)
	if err != nil {
		l.logError(err, "打开PDF文件失败")
		return nil, err
	}
	defer f.Close()

	// 获取页面数
	numPages, err := pdfReader.GetNumPages()
	if err != nil {
		l.logError(err, "获取PDF页数失败")
		return nil, err
	}

	// 提取文本内容
	var fullText string
	pageTexts := make([]string, numPages)

	for i := 0; i < numPages; i++ {
		pageNum := i + 1
		page, err := pdfReader.GetPage(pageNum)
		if err != nil {
			l.logError(err, fmt.Sprintf("获取PDF第%d页失败", pageNum))
			continue
		}

		// 创建文本提取器
		extractor, err := extractor.New(page)
		if err != nil {
			l.logError(err, fmt.Sprintf("创建PDF提取器失败，第%d页", pageNum))
			continue
		}

		// 提取文本
		text, err := extractor.ExtractText()
		if err != nil {
			l.logError(err, fmt.Sprintf("提取PDF第%d页文本失败", pageNum))
			continue
		}

		pageTexts[i] = text
		fullText += text + "\n\n"
	}

	// 创建文档对象
	doc := Document{
		Content: fullText,
		MetaData: map[string]interface{}{
			"file_path":    l.FilePath,
			"file_name":    filepath.Base(l.FilePath),
			"file_ext":     "pdf",
			"content_type": "application/pdf",
			"loader_type":  "PDFLoader",
			"load_time":    startTime.Format(time.RFC3339),
			"content_size": len(fullText),
			"page_count":   numPages,
			"page_texts":   pageTexts,
		},
		FilePath: l.FilePath,
	}

	l.logInfo("PDF文件加载成功", map[string]interface{}{
		"page_count":   numPages,
		"content_size": len(fullText),
		"load_time_ms": time.Since(startTime).Milliseconds(),
	})

	return []Document{doc}, nil
}
